package myJs.user.data

import myJs.Implicits._
import myJs.Utils._
import myJs.myPkg._
import myJs.myPkg.jquery._
import myJs.tool.Pojo.FilterContentData
import myJs.Utils
import myJs.tool.Tool
import org.scalajs.dom._
import org.scalajs.dom.ext.Ajax
import scalatags.Text.all._

import scala.collection.immutable.SeqMap
import scala.concurrent.Future
import scala.scalajs.js
import scala.scalajs.js.Dynamic.{global => g}
import scala.scalajs.js.annotation.{JSExport, JSExportTopLevel}
import scala.scalajs.js.JSConverters._
import scala.concurrent.ExecutionContext.Implicits.global
import scala.scalajs.js.JSON

/**
 * Created by yz on 16/9/2021
 */
@JSExportTopLevel("SampleManage")
object SampleManage {

  var tableRs: JArJDJAn = _
  val tableId = "table"
  val formId = "form"
  val updateModalId = "updateModal"

  def updateFormJq = $(s"#${updateModalId} #${formId}")

  @JSExport("init")
  def init = {
    initTable
    refreshTableB
    bootStrapValidator
    registerEvent
  }

  def tableFilterEvent = {
    Tool.clickHide

    $(document.body).on("click", s".myOperate", "", (y: Element) => {
      Tool.filterContentShowFront(y)
    })
    $(document.body).on("click", s".mySortLi", "", (y: Element) => {
      Tool.execSort(y, "", () => {
        refreshTable
      })
    })
    $(document.body).on("click", s".myConfirm", "", (y: Element) => {
      Tool.confirmFilter(y, "", () => {
        refreshTable
      })
    })
    $(document.body).on("click", s".myHide", "", (y: Element) => {
      Tool.hideFilterContent(y)
    })
    $(document.body).on("click", s".myRemove", "", (y: Element) => {
      Tool.removeCondition(y, "", () => {
        refreshTable
      })
    })
    $(document.body).on("click", s".myRemoveSort", "", (y: Element) => {
      Tool.removeSort(y, "", () => {
        refreshTable
      })
    })
  }

  def registerEvent = {
    tableFilterEvent

    $(document.body).on("click", s".myDelete", "", (y: Element) => {
      val id = $(y).dataValue
      deleteData(id)
    })
    $(document.body).on("click", s".idsButton", "", (y: Element) => {
      deletes
    })
    $(document.body).on("click", s".myUpdateShow", "", (y: Element) => {
      val id = $(y).dataValue
      updateShow(id)
    })
    $(document.body).on("click", s".myUpdate", "", (y: Element) => {
      update
    })
    $(document.body).on("change fileclear", s".file", "", (y: Element) => {
      $(y).parents("form").bv.revalidateField("file")
    })
    $(s"#${updateModalId}").on("shown.bs.modal", () => {
      $(s"#${updateModalId} #${formId}").bv.revalidateField("sampleName").revalidateField("describe")
    })
  }

  def update = {
    val formJq = updateFormJq
    val bv = formJq.bv
    bv.validate()
    val valid = bv.isValid()
    if (valid) {
      val index = layer.alert(Tool.myElement, Tool.layerOptions)
      val url = g.jsRoutes.controllers.DataController.updateSample().url.toString
      val formData = formJq.serialize()
      Ajax.post(url = s"${url}", data = formData, headers = Map("Content-Type" -> "application/x-www-form-urlencoded"),
        responseType = "application/json").map { xhr =>
        refreshTableB { () =>
          layer.close(index)
          $(s"#${updateModalId}").modal("hide")
          Swal.swal(SwalOptions.title("成功").text("修改成功!").`type`("success"))
        }
      }
    }
  }

  def updateShow(id: String) = {
    val url = g.jsRoutes.controllers.DataController.getSampleById().url.toString
    Ajax.get(url = s"${url}?id=${id}", headers = Map("Content-Type" -> "application/json")).map { xhr =>
      val rs = xhr.responseText.toJDJAn
      Tool.fillByNames(rs.toMyJDS, updateFormJq)
      $(s"#${updateModalId}").modal("show")
    }
  }

  def deleteData(id: String) = {
    val options = SwalOptions.title("").text("确定要删除此数据吗？").`type`("warning").showCancelButton(true).
      showConfirmButton(true).confirmButtonClass(Tool.confirmButtonClass).confirmButtonText("确定").closeOnConfirm(false).
      cancelButtonText("取消").showLoaderOnConfirm(true).cancelButtonClass(Tool.cancelButtonClass)
    Swal.swal(options, () => {
      execDelete(List(id))
    })
  }

  def deletes = {
    val ids = Tool.getIdsValue()
    val options = SwalOptions.title("").text("确定要将选中的数据删除吗？").`type`("warning").showCancelButton(true).
      showConfirmButton(true).confirmButtonClass(Tool.confirmButtonClass).confirmButtonText("确定").closeOnConfirm(false).
      cancelButtonText("取消").cancelButtonClass(Tool.cancelButtonClass)
    Swal.swal(options, () => {
      execDelete(ids)
    })
  }

  def execDelete(ids: List[String]) = {
    val data = js.Dictionary(
      "ids" -> ids.toJSArray
    )
    val url = g.jsRoutes.controllers.DataController.deleteSamples().url.toString
    Ajax.delete(url = s"${
      url
    }", data = JSON.stringify(data),
      headers = Map("Content-Type" -> "application/json"), responseType = "blob").map {
      xhr =>
        refreshTableB(
          () => {
            Swal.swal(SwalOptions.title("成功").text(s"删除成功！").`type`("success"))
            Tool.getIds()
          }
        )
    }
  }

  def refreshTableB: Future[Any] = {
    refreshTableB(() => ())
  }

  def refreshTableB(f: () => Any): Future[Any] = {
    refreshTableRs.map { x =>
      refreshTable(f)
    }
  }

  def refreshTableRs = {
    val url = g.jsRoutes.controllers.DataController.getAllSample().url.toString
    Ajax.get(url = s"${url}", headers = Map("Content-Type" -> "application/json")).map { xhr =>
      tableRs = xhr.responseText.toJArJDJAn
    }
  }

  def refreshTable: Any = {
    refreshTable(() => ())
  }

  def refreshTable(f: () => Any): Any = {
    val queryMap = Tool.getQueryMap("")
    val sortData = Tool.sortExec(tableRs, queryMap)
    val filterData = Tool.execFilter(sortData = sortData, queryMap = queryMap, getColumnV = getColumnV)
    $(s"#${tableId}").bootstrapTable("load", filterData)
    f()
  }

  def initFilterContent(tabId: String, map: SeqMap[String, String]) = {
    val textSortDatas = List(
      FilterContentData("sampleName", map("sampleName")),
      FilterContentData("describe", map("describe")),
    )
    val rangeSortDatas = List(
      FilterContentData("max", map("max")),
      FilterContentData("min", map("min")),
      FilterContentData("mean", map("mean")),
      FilterContentData("size", map("size")),
    )
    val timeSortDatas = List(
      FilterContentData("uploadTime", map("uploadTime"))
    )
    Tool.initFilterContent(textSortDatas = textSortDatas, rangeSortDatas = rangeSortDatas,
      timeSortDatas = timeSortDatas, parentId = s"${tabId}")
    textSortDatas ::: rangeSortDatas ::: timeSortDatas
  }

  def getColumnV(columnName: String, v: js.Any) = columnName match {
    case _ =>
      v.toString
  }

  def tbFmt(columnName: String): js.Function = (v: js.Any, row: js.Dictionary[js.Any]) => columnName match {
    case x => getColumnV(x, v)
  }

  @JSExport("operateFmt")
  def operateFmt: js.Function = {
    (v: js.Any, row: js.Dictionary[js.Any]) =>

      val resetStr = a(`class` := "btn btn-success btn-xs myUpdateShow",
        dataValue := s"${row("id")}",
        cursor.pointer,
        span(
          em(cls := "fa fa-edit", "修改")
        )
      )
      val deleteStr = a(`class` := "btn btn-danger btn-xs myDelete",
        title := "删除", dataValue := s"${row("id")}",
        cursor.pointer,
        target := "_blank",
        span(
          em(cls := "fa fa-remove", "删除")
        )
      )
      Array(resetStr, deleteStr).mkString("&nbsp;")
  }

  val operateColumn = js.Array(
    ColumnOptions.field("operate").title("操作").formatter(operateFmt).filterControl("clear")
  )

  val checkColumn = ColumnOptions.field("check").checkbox(true)

  def initTable = {
    val tableId = "table"
    val map = SeqMap("sampleName" -> "文件名", "max" -> "最大序列长度（bp）", "min" -> "最小序列长度（bp）",
      "mean" -> "平均序列长度（bp）", "size" -> "序列条数", "describe" -> "描述",
      "uploadTime" -> "上传时间")
    val columnNames = map.keyList
    val allDatas = initFilterContent("", map)
    val columns = columnNames.map { columnName =>
      val title = map.getOrElse(columnName, columnName)
      val fmt = tbFmt(columnName)
      val basicOptions = ColumnOptions.field(columnName).title(title).sortable(false).formatter(fmt)
      columnName match {
        case x if allDatas.map(_.fieldName).contains(x) => basicOptions.
          sortable(false).operateable(true)
        case _ => basicOptions
      }
    }.concat(operateColumn)
    val options = TableOptions.columns(columns.toJSArray).searchOnButton(false).filterControl(false).locale("zh-CN").
      search(false)
    $(s"#${tableId}").bootstrapTable(options)
    Tool.dateInit
    Tool.bindEvt()
  }

  def myRun = {
    val formJq = $("#form")
    val bv = formJq.bv
    bv.validate()
    val valid = bv.isValid()
    if (valid) {
      val element = div(id := "content",
        span(id := "info", "文件上传中",
          span(id := "progress")), " ",
        img(src := "/assets/images/running2.gif", cls := "runningImage", width := 30, height := 20)
      ).render
      val layerOptions = LayerOptions.icon(16).shade(0.01).time(20000000)
      val index = layer.msg(element, layerOptions)
      val formData = new FormData(formJq(0).toHTMLFormElement)
      val url = g.jsRoutes.controllers.DataController.loadData().url.toString
      val xhr = new XMLHttpRequest
      xhr.open("post", url)
      xhr.upload.onprogress = Utils.progressHandlingFunction
      xhr.onreadystatechange = (e) => {
        if (xhr.readyState == XMLHttpRequest.DONE) {
          val rs = xhr.responseText.toJDJAn
          layer.close(index)
          val valid = rs("valid").toB
          if (valid) {
            Swal.swal(SwalOptions.title("成功").text("导入数据成功!").`type`("success"))
          } else {
            g.swal("Error", rs.myGet("message"), "error")
          }
        }
      }
      xhr.send(formData)
    }
  }

  def bootStrapValidator = {
    val url = g.jsRoutes.controllers.DataController.sampleNameCheck().url.toString

    def dataF: js.Function = (validator: BootstrapValidator) => {
      js.Dictionary(
        "sampleName" -> validator.getFieldElements("sampleName").myVal,
        "id" -> validator.getFieldElements("id").myVal,
      )
    }

    val maxNumber = Double.MaxValue
    val dict: js.Dictionary[js.Any] = js.Dictionary(
      "feedbackIcons" -> js.Dictionary(
        "valid" -> "glyphicon glyphicon-ok",
        "invalid" -> "glyphicon glyphicon-remove",
        "validating" -> "glyphicon glyphicon-refresh",
      ),
      "fields" -> js.Dictionary(
        "sampleName" -> {
          val info = "文件名"
          js.Dictionary(
            "validators" -> js.Dictionary(
              "notEmpty" -> js.Dictionary(
                "message" -> s"${info}不能为空！"
              ),
              "remote" -> js.Dictionary(
                "message" -> s"${info}已存在！",
                "url" -> url,
                "delay" -> 1000,
                "type" -> "POST",
                "data" -> dataF
              ),
            )
          )
        },
        "describe" -> {
          val info = "描述"
          js.Dictionary(
            "validators" -> js.Dictionary(
              "notEmpty" -> js.Dictionary(
                "message" -> s"${info}不能为空！"
              ),
            )
          )
        },
      )
    )
    $(s"#form").bootstrapValidator(dict)
  }


}
